/*
    Copyright (C) 2011  Jiabo <jiabo2011@gmail.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#undef EAX
#define EAX (env->regs[R_EAX])
#undef ECX
#define ECX (env->regs[R_ECX])
#undef EDX
#define EDX (env->regs[R_EDX])
#undef EBX
#define EBX (env->regs[R_EBX])
#undef ESP
#define ESP (env->regs[R_ESP])
#undef EBP
#define EBP (env->regs[R_EBP])
#undef ESI
#define ESI (env->regs[R_ESI])
#undef EDI
#define EDI (env->regs[R_EDI])
#undef EIP
#define EIP (env->eip)
#define DF  (env->df)

void gen_div(CPUX86State *env, int ot, uint32_t divider)
{
	unsigned int dividend, q, r;

//	if (divider == 0) {
//		raise_exception(EXCP00_DIVZ);
//	}
	switch (ot) {
	case OT_BYTE:
		dividend = (uint16_t)EAX;
		q = (dividend / divider);
//		if (q > 0xff)
//			raise_exception(EXCP00_DIVZ);
		r = (dividend % divider) & 0xff;
		EAX = (EAX & ~0xffff) | (r << 8) | q;
		break;
	case OT_WORD:
		dividend = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
		q = (dividend / divider);
//		if (q > 0xffff)
//			raise_exception(EXCP00_DIVZ);
		r = (dividend % divider) & 0xffff;
		EAX = (EAX & ~0xffff) | q;
		EDX = (EDX & ~0xffff) | r;
		break;
	case OT_LONG:
	{
		uint64_t dividend64, q64;

		dividend64 = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
		q64 = (dividend64 / divider);
		r = (dividend64 % divider);
//		if (q64 > 0xffffffff)
//			raise_exception(EXCP00_DIVZ);
		EAX = (uint32_t)q64;
		EDX = (uint32_t)r;
		break;
	}
	}
}

void gen_idiv(CPUX86State *env, int ot, int32_t divider)
{
	int dividend, q, r;

//	if (divider == 0) {
//		raise_exception(EXCP00_DIVZ);
//	}
	switch (ot) {
	case OT_BYTE:
		dividend = (int16_t)EAX;
		q = (dividend / divider);
//		if (q > 0xff)
//			raise_exception(EXCP00_DIVZ);
		r = (dividend % divider) & 0xff;
		EAX = (EAX & ~0xffff) | (r << 8) | q;
		break;
	case OT_WORD:
		dividend = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
		q = (dividend / divider);
//		if (q > 0xffff)
//			raise_exception(EXCP00_DIVZ);
		r = (dividend % divider) & 0xffff;
		EAX = (EAX & ~0xffff) | q;
		EDX = (EDX & ~0xffff) | r;
		break;
	case OT_LONG:
	{
		int64_t dividend64, q64;

		dividend64 = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
		q64 = (dividend64 / divider);
		r = (dividend64 % divider);
//		if (q64 > 0xffffffff)
//			raise_exception(EXCP00_DIVZ);
		EAX = (uint32_t)q64;
		EDX = (uint32_t)r;
		break;
	}
	}
}
